82% מכלל משתמשי האינטרנט שוכחים סיסמאות. מספר שלכאורה מפתיע, אך הגינוי, בהתחשב בזה שמרבית הגולשים לא מומחים טכנולוגיים מי-יודע-מה. מחקרים מראים שכ-65% מהמשתמשים רושמים את הסיסמאות על דף, שכנראה נעלם לקראת ל"ג בעומר, שוכחים את הסיסמה באופן קבוע (25%) ומשתפים סיסמאות עם שותפים (33%).
כאן הזמן לתת מחמאה לקהילת המפתחים הישראלית, שלא שוכחת את הסיסמאות שלה. ובכלל, כאן באתר, לא נשכחה בחודש האחרון אף סיסמה מלבד הסיסמה שלי, שנשכחה כמה עשרות פעמים ומכמה כתובות ip שונות.
עכשיו כשהסיסמה בידיים הנכונות, אספר איך ליצור כפתור "שכחתי סיסמה" בצורה נכונה ועל מה צריך לחשוב. אין שום דבר מסובך בהמשך ואם אתה כבר יודע ליצור כפתורי שחזור סיסמה, כנראה שלא אחדש לך שום דבר.
שחזור סיסמה מתחיל, כמובן, מסיסמה.
אם אתה עדיין לא יודע לשמור סיסמאות נכון במסד ולבצע הזדהות נכונה באמצעות פונקציות לעבודה עם סיסמאות, עצור עכשיו, קרא את המדריך וחזור לאחר מכן, אחרת עלית על רכבת בכיוון הפוך.
עכשיו הגיע הזמן ליצור טופס עם כפתור שחזור, אבל לפני זה שכחתי לומר לך דבר אחד חשוב. מסתבר, שבאתרים כמו זה, אנשים שוכחים לא רק את הסיסמה, אלא גם את כתובת המייל שאיתה נרשמו וגם את שם המשתמש שבו בחרו.
עכשיו יותר מעניין? טוב, לא הכל בבת אחת. קודם סיסמה ושני מקרים פשוטים:
במקרה הראשון: המשתמש שכח את הסיסמה של עצמו
במקרה השני: מישהו מנסה לשחזר סיסמה של מישהו אחר.
כדי למנוע מהמשתמשים שלך הפתעות לא נעימות רצוי לא לשכוח גם מהמקרה השני לאורך כל הדרך.
אם ההזדהות אצלך באתר מתבצעת באמצעות כתובת מייל, המקרה השני הופך לפחות רלוונטי.
אם ההזדהות היא לפי שם משתמש וסיסמה, אני ממליץ להכניס שלב ביניים ולהציע למשתמש להזין גם את כתובת המייל, יחד עם רמז קטן בצורת כתובת המייל חצי חבויה:
במקרה הזה מספיק שהאדם הזין את שם המשתמש שלו באתר ולפי שם המשתמש תוכל לשלוף מהמסד את כתובת המייל, להחליף כמה אותיות בכוכביות בצורה שרירותית ולהציג לו.
רק במקרה הזה אתה מבטיח שהמשתמש לא יקבל לכתובת הדואר שלו הודעות עם הצעה לשינוי סיסמה כל פעם שמישהו אחר מנסה לשחזר סיסמה במקומו. פשוט וקל עד עכשיו.
כשביררנו שהמשתמש אמיתי
נוכל לשלוח הצעה לשחזור סיסמה לכתובת המייל שהוא הזין .
גם כאן לרשותינו שני אפשרויות:
- לשנות את הסיסמה ולשלוח לו סיסמה חדשה למייל
- או להפנות לעמוד מיוחד שבו יוכל לבחור לעצמו סיסמה חדשה.
מבחינה טכנית שני הפתרונות די דומים, אך אני ממליץ על הפתרון השני מניסיון אישי. הפתרון הראשון הוא מתכון 100% לקבל בקשה לשחזור סיסמה שוב פעם בעוד יומיים. אף אחד לא נכנס לפאנל ניהול להחליף סיסמה אם לא דרשת את זה במפורש. בייחוד באתרים שאתה צריך בדיוק לשלוש דקות, כמו הזמנת פיצה.
דרישות לשחזור סיסמה
כדי שהמשתמש ישמח לקבל את מייל השחזור שלו עם לב שלם
- רצוי שזה יהיה מייל חד פעמי ומישהו לא יוכל בטעות להשתמש באותו קישור לשחזור סיסמה פעמיים
- לקישור יהיה תוקף מסוים, רק לחמש הדקות הקרובות
- יהיה קשה לנחש אותו (לא setNewPassword.php?userid=1 )
קישור יותר חכם יכלול מחרוזת מקרית כלשהי שתבטיח שאף אחד לא ניחש אותה, ובנוסף תכלול מספיק מידע לזיהוי המשתמש. למשל:
setNewPassword.php?key=KnYfme9XleLX8lJFux2aM1
כל מה שנשאר לנו, הוא ליצור טבלה במסד נתונים עם השדות:
- מספר משתמש
- מפתח רדומלי
- כתובת IP
- תוקף בצורת תאריך ושעה:
CREATE TABLE IF NOT EXISTS `password_recovery` (
`userid` bigint(20) unsigned DEFAULT NULL,
`key` varchar(20) NOT NULL,
`validity` datetime NOT NULL,
`ip` varchar(45) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `password_recovery`
ADD PRIMARY KEY (`key`)
`userid` bigint(20) unsigned DEFAULT NULL,
`key` varchar(20) NOT NULL,
`validity` datetime NOT NULL,
`ip` varchar(45) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `password_recovery`
ADD PRIMARY KEY (`key`)
החלק הפשוט, הקוד
עכשיו נשאר החלק הקל: להכניס שורה למסד כאשר המשתמש שולח את טופס השחזור
ולשלוף שורה כאשר מישהו נכנס לקישור המיוחד
if(isValidEmail($_POST['email']))
{
$userId = SELECT userid FROM users WHERE email = $_POST['email']
$key =generateRandomString(20);
$validUntil = time() + 10 * 60; // +10 minutes from now
$ip = $_SERVER['REMOTE_ADDR'];
INSERT INTO password_recovery VALUES($userId, $key, $validity, $ip)
}
{
$userId = SELECT userid FROM users WHERE email = $_POST['email']
$key =generateRandomString(20);
$validUntil = time() + 10 * 60; // +10 minutes from now
$ip = $_SERVER['REMOTE_ADDR'];
INSERT INTO password_recovery VALUES($userId, $key, $validity, $ip)
}
אני בטוח שאתה יכול לכתוב את השאר, בלי לשכוח לבדוק שאשכרה נמצא משתמש עם מייל כזה במסד.
אולי יעזור לך: פונקציה ליצירת מחרוזת רנדומלית ובדיקת תקינות אימייל.
ומה צריך להיות בעמוד שחזור סיסמה שאליו מוביל הקישור? בסך הכל הפעולה ההפוכה:
$key = $_GET['key'];
$row = SELECT * FROM password_recovery WHERE key=$key and validity > NOW()
$_SESSION['userid'] = $row['userid'];
$_SESSION['allowPassReset'] = true;
?>
<form></form>
$row = SELECT * FROM password_recovery WHERE key=$key and validity > NOW()
$_SESSION['userid'] = $row['userid'];
$_SESSION['allowPassReset'] = true;
?>
<form></form>
וזהו, אפשר להציג למשתמש את תופס שחזור הסיסמה.
שום דבר קשה, נכון?
ואם אתה תוהה בשביל מה allowPassReset בסשן, אז בוא ניזכר לרגע שאנחנו הולכים לאפשר למשתמש להחליף סיסמה בלי לדעת את הסיסמה הישנה. את הסיסמה הישנה בדרך כלל מבקשים כדי שלא ישנה לך את הסיסמה בפייסבוק חבר שיתישב לך על המחשב אחרי שסימנת "זכור אותי".
כדי שהחבר הזדוני לא יוכל לגשת לעמוד הזה ולשנות את הסיסמה בלי לדעת את הסיסמה הישנה - נצטרך להגביל גישה לעמוד השינוי ואת זה נוכל לעשות או באמצעות בדיקה שנית של key או על ידי המפתח הזה בסשן. מה שעדיף, בגלל שלבדוק key שוב צריך מול מסד.
יש לך שאלות? רשום בתגובה, אם לא שכחת סיסמה..
תגובות לכתבה:
יפה יפה! אהבתי מאוד. מדוייק.
תודה רבה לך! האתר קצת "מת" לאחרונה.. :(
כשיצרת את הטבלה, למה הוספת את key כמפתח ראשי ולא את userid ?
בגלל שאם הקישור שלך נראה כמו שאצלי
setNewPassword.php?key=KnYfme9XleLX8lJFux2aM1
את החיפוש בטבלה אתה תעשה לפי ה-key ולא לפי userid
חוץ מזה, אותו משתמש יכול לבקש שחזור סיסמה מספר פעמים, ומפתח ראשי על עמודת יוזר ימנע ממנו ליצור שני שורות בטבלה, מה שיצריך ממך עוד קוד שיבדוק האם כבר יש מפתח שהוא בתוקף לאותו משתמש וקוד שידאג למחוק שורות ישנות.